//
//  HttpRequest.swift
//  网络请求
//
//  Created by emma on 2024/4/19.
//

import UIKit

//根据RFC2616，HTTP Method是区分大小写的，而Header是不区分的。
public enum HttpMethod: String {
    case get = "GET"
    case post = "POST"
    case delete = "DELETE"
}

class HttpRequest: NSObject {
    static let version = "v1.0.9"
    static let boundary = "BOUNDARY"//分割标识符
    //MARK: - http请求
    ///httpMethod 请求方式
    ///path 请求路径 这里是相对路径
    ///parameters 请求参数
    ///success 请求成功回调
    ///failure 请求失败回调
    class func http(_ httpMethod: HttpMethod, _ urlString: String, _ parameters: [String : Any]?, success: @escaping ((_ result: [String : Any]) -> ()), failure: @escaping ((_ error: Error?) -> ())) {
        var allPath = urlString//全路径
        var parameterString = ""//参数拼接字符串
        var url: URL!
        var urlRequest: URLRequest!
        var i = 0
        if let params = parameters {
            for (key,value) in params {
                if i == 0 { parameterString += "\(key)=\(value)" }
                else { parameterString += "&\(key)=\(value)" }
                i += 1
            }
        }
        if httpMethod == .get || httpMethod == .delete {
            allPath = allPath + "?" + parameterString
            url = URL(string: allPath.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")
            guard let url = url else { return }
            urlRequest = URLRequest(url: url)
        }else if httpMethod == .post {
            url = URL(string: allPath)
            guard let url = url else { return }
            urlRequest = URLRequest(url: url)
            urlRequest.httpBody = parameterString.data(using: .utf8)
        }else {}
        MyLog("请求url:\(allPath)")
        MyLog("请求方式:\(httpMethod.rawValue)")
        //MyLog(getToken())
        urlRequest.timeoutInterval = 30
        urlRequest.httpMethod = httpMethod.rawValue
        //urlRequest.addValue(getToken(), forHTTPHeaderField: "token")
        urlRequest.addValue(version, forHTTPHeaderField: "version")
        urlRequest.addValue("iOS", forHTTPHeaderField: "device")
        
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlRequest) { (data, respond, error) in
            if data == nil { failure(error); return }
            if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] {
                let code = json.int("code")
                if code == 403 {
                }else {
                    MyLog(json)
                    success(json)
                }
            } else {
                MyLog("fail")
                failure(error)
            }
        }
        dataTask.resume()
    }
    //MARK: - get请求
    class func get(_ path: String, _ parameters: [String : Any]?,success: @escaping ((_ result: [String : Any]) -> ()),failure: @escaping ((_ error: Error?) -> ())) {
        var allPath = path//全路径
        var i = 0
        if let paras = parameters {
            for (key,value) in paras {
                if i == 0 { allPath += "?\(key)=\(value)" }
                else { allPath += "&\(key)=\(value)" }
                i += 1
            }
        }
        MyLog("-----请求url:\(allPath)-----")
        //MyLog(getToken())
        let url = URL(string: allPath)
        guard let url = url else { return }
        var urlRequest = URLRequest(url: url)
        urlRequest.timeoutInterval = 30
        urlRequest.httpMethod = "GET"
        //urlRequest.addValue(getToken(), forHTTPHeaderField: "token")
        urlRequest.addValue(version, forHTTPHeaderField: "version")
        urlRequest.addValue("iOS", forHTTPHeaderField: "device")
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlRequest) { (data, respond, error) in
            if data == nil { failure(error); return }
            if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] { MyLog(json); success(json) }
            else { MyLog("fail"); failure(error) }
        }
        dataTask.resume()
    }
    class func get(_ path: String, _ parameters: [String : Any]?,response: @escaping ((_ result: [String : Any]) -> ())) {
        var allPath = path//全路径
        var i = 0
        if let paras = parameters {
            for (key,value) in paras {
                if i == 0 { allPath += "?\(key)=\(value)" }
                else { allPath += "&\(key)=\(value)" }
                i += 1
            }
        }
        MyLog("-----请求url:\(allPath)-----")
        //MyLog(getToken())
        let url = URL(string: allPath)
        guard let url = url else { return }
        var urlRequest = URLRequest(url: url)
        urlRequest.timeoutInterval = 30
        urlRequest.httpMethod = "GET"
        //urlRequest.addValue(getToken(), forHTTPHeaderField: "token")
        urlRequest.addValue(version, forHTTPHeaderField: "version")
        urlRequest.addValue("iOS", forHTTPHeaderField: "device")
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlRequest) { (data, respond, error) in
            if data == nil { MyLog("fail"); response([String : Any]()); return }
            if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] { response(json) }
            else { MyLog("fail"); response([String : Any]()) }
        }
        dataTask.resume()
    }
    //MARK: - post请求
    class func post(_ path: String, _ parameters: [String : Any]?, success: @escaping ((_ result: [String : Any]) -> ()),failure: @escaping ((_ error: Error?) -> ())) {
        var parameterString = ""//参数拼接字符串
        var i = 0
        if let paras = parameters {
            for (key,value) in paras {
                if i == 0 { parameterString += "\(key)=\(value)" }
                else { parameterString += "&\(key)=\(value)" }
                i += 1
            }
        }
        MyLog("-----请求接口:\(path)-----")
        MyLog("-----请求参数:\(parameterString)-----")
        let url = URL(string: path)
        guard let url = url else { return }
        var urlRequest = URLRequest(url: url)
        urlRequest.timeoutInterval = 30
        urlRequest.httpMethod = "POST"
        urlRequest.httpBody = parameterString.data(using: .utf8)
        //MyLog(getToken())
        //urlRequest.addValue(getToken(), forHTTPHeaderField: "token")
        urlRequest.addValue(version, forHTTPHeaderField: "version")
        urlRequest.addValue("iOS", forHTTPHeaderField: "device")
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlRequest) { (data, respond, error) in
            if data == nil { failure(error); return }
            if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] { MyLog(json); success(json) }
            else { MyLog("fail"); failure(error) }
        }
        dataTask.resume()
    }
    //默认, "Content-Type":"application/x-www-form-urlencoded"
    class func post(_ path: String, _ parameters: [String : Any]?, response: @escaping ((_ result: [String : Any]) -> ())) {
        var parameterString = ""//参数拼接字符串
        var i = 0
        if let paras = parameters {
            for (key,value) in paras {
                if i == 0 { parameterString += "\(key)=\(value)" }
                else { parameterString += "&\(key)=\(value)" }
                i += 1
            }
        }
        MyLog("-----请求接口:\(path)-----")
        MyLog("-----请求参数:\(parameterString)-----")
        let url = URL(string: path)
        guard let url = url else { return }
        var urlRequest = URLRequest(url: url)
        urlRequest.timeoutInterval = 30
        urlRequest.httpMethod = "POST"
        urlRequest.httpBody = parameterString.data(using: .utf8)
        
        let session = URLSession.shared
        let dataTask = session.dataTask(with: urlRequest) { (data, respond, error) in
            DispatchQueue.main.async {
                if data == nil {
                    MyLog("fail")
                    response([String : Any]())
                    return
                }
                if let value = data {
                    MyLog(String(data: value, encoding: String.Encoding.utf8))
                }else {
                    MyLog(data)
                }
                if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] {
                    response(json)
                }else {
                    MyLog("fail")
                    response([String : Any]())
                }
            }
        }
        dataTask.resume()
    }
    //MARK: - 下载文件
    class func download(_ urlString: String,success: @escaping ((_ result: Data?) -> ()),failure: @escaping ((_ error: Error) -> ())) {
        MyLog("-----请求接口:\(urlString)-----")
        let url = URL(string: urlString)
        guard let url = url else { return }
        var request = URLRequest(url: url)
        request.cachePolicy = .returnCacheDataElseLoad//缓存策略
        request.timeoutInterval = 30
        //urlRequest.httpMethod = "GET"
        //MyLog(getToken())
        //urlRequest.addValue(getToken(), forHTTPHeaderField: "token")
        //urlRequest.addValue(Date().timeStamp, forHTTPHeaderField: "timestamp")
        //urlRequest.addValue(version, forHTTPHeaderField: "version")
        //urlRequest.addValue("ios", forHTTPHeaderField: "apptype")
        let session = URLSession.shared
        let dataTask = session.dataTask(with: request) { (data, respond, error) in
            MyLog(data)
            DispatchQueue.main.async {
                if data != nil { success(data) }
                else { failure(error!) }
            }
        }
        dataTask.resume()
    }
    // MARK:- 上传图片/文件
    class func upload(_ parameters: [String : Any]?, _ formData: Data, response: @escaping ((_ result: [String : Any]) -> ())) {
        let allPath =  "/image/upload"
        let url = URL(string: allPath)
        guard let url = url else { return }
        let body = NSMutableData()//组装body
        if let paras = parameters {
            for(key, value) in paras {
                body.append(NSString(format:"--\(boundary)\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
                body.append(NSString(format:"Content-Disposition:form-data;name=\"\(key)\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
                body.append(NSString(format:"\(value)" as NSString).data(using: String.Encoding.utf8.rawValue)!)
                body.append(NSString(format:"\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
            }
        }//拼接参数
        MyLog("-----请求接口:\(allPath)-----")
        MyLog("-----请求参数:\(body)-----")
        body.append(formData)//拼接文件/图片
        body.append(NSString(format:"\r\n--\(boundary)--\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)//拼接结尾
        let request = NSMutableURLRequest(url: url)
        request.timeoutInterval = 30
        request.httpMethod = "POST"
        //上传文件必须设置---Content-Type
        let contentType = "multipart/form-data;boundary="+boundary
        request.addValue(contentType, forHTTPHeaderField:"Content-Type")
        request.httpBody = body as Data
        //MyLog(getToken())
        //request.addValue(getToken(), forHTTPHeaderField: "token")
        request.addValue(version, forHTTPHeaderField: "version")
        request.addValue("iOS", forHTTPHeaderField: "device")
        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest) { (data, respond, error) in
            if data == nil { MyLog("fail"); response([String : Any]()); return }
            if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] { MyLog(json); response(json) }
            else { MyLog("fail"); response([String : Any]()) }
        }
        dataTask.resume()
    }
    //MARK: - 上传一张图片 返回图片路径
    class func uploadImage(_ image: UIImage, _ parameters: [String : Any]?, response: @escaping ((_ path: String) -> ())) {
        //guard let data = image.compressToData(maxSize: 2048) else { return }
        let formData = NSMutableData()
        //formData.appendPartWithFileData(fileData: data, name: "file", fileName: "fileName.jpg", mimeType: "image/jpg")
        let allPath = "/image/upload"
        let url = URL(string: allPath)
        guard let url = url else { return }
        let body = NSMutableData()//组装body
        if let paras = parameters {
            for(key, value) in paras {
                body.append(NSString(format:"--\(boundary)\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
                body.append(NSString(format:"Content-Disposition:form-data;name=\"\(key)\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
                body.append(NSString(format:"\(value)" as NSString).data(using: String.Encoding.utf8.rawValue)!)
                body.append(NSString(format:"\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
            }
        }//拼接参数
        MyLog("-----请求接口:\(allPath)-----")
        MyLog("-----请求参数:\(body)-----")
        body.append(formData as Data)//拼接文件/图片
        body.append(NSString(format:"\r\n--\(boundary)--\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)//拼接结尾
        let request=NSMutableURLRequest(url: url)
        request.timeoutInterval = 30
        request.httpMethod="POST"
        //上传文件必须设置---Content-Type
        let contentType:String="multipart/form-data;boundary="+boundary
        request.addValue(contentType, forHTTPHeaderField:"Content-Type")
        request.httpBody = body as Data
        //request.addValue(getToken(), forHTTPHeaderField: "token")
        request.addValue(version, forHTTPHeaderField: "version")
        request.addValue("iOS", forHTTPHeaderField: "device")
        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest) { (data, respond, error) in
//            if let value = data { MyLog(String(data: value, encoding: String.Encoding.utf8)) }
//            else { MyLog(data) }
            if data == nil {
                MyLog("fail"); return
            }
            if let json = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] {
//                if json.string("code") == "200" {
//                    //DispatchQueue.main.async { ProgressHUD.showOnlyText("上传成功") }
//                    response(json.dictionary("data").string("path"))
//                }else {
//                    MyLog("fail");
//                }
            }else { MyLog("fail") }
        }
        dataTask.resume()
    }
}
extension NSMutableData {
    func appendPartWithFileData(fileData: Data, name: String, fileName: String, mimeType: String) {
        self.append(("--BOUNDARY\r\n" as String).data(using: String.Encoding.utf8)!)
        self.append(("Content-Disposition:form-data;name=\"\(name)\";filename=\"\(fileName)\"\r\n" as String).data(using: String.Encoding.utf8)!)
        self.append(("Content-Type:\(mimeType)\r\n" as String).data(using: String.Encoding.utf8)!)
        self.append(("Content-Transfer-Encoding: binary\r\n\r\n" as String).data(using: String.Encoding.utf8)!)
        self.append(fileData)
        self.append(("\r\n" as String).data(using: String.Encoding.utf8)!)
    }
}
